/*
 * FaceCat图形通讯框架
 * 著作权编号:2015SR229355+2020SR0266727
 * 上海卷卷猫信息技术有限公司
 */

using System;
using System.Collections.Generic;

namespace FaceCat {
    /// <summary>
    /// 树视图
    /// </summary>
    public class FCTree : FCGrid
    {
        /// <summary>
        /// 创建树
        /// </summary>
        public FCTree()
        {
            setGridLineColor(FCColor.None);
        }

        /// <summary>
        /// 正在移动的节点
        /// </summary>
        public FCTreeNode m_movingNode;

        /// <summary>
        /// 子节点
        /// </summary>
        public ArrayList<FCTreeNode> m_nodes = new ArrayList<FCTreeNode>();

        public bool m_checkBoxes;

        /// <summary>
        /// 获取是否在节点旁显示复选框
        /// </summary>
        public virtual bool hasCheckBoxes()
        {
            return m_checkBoxes;
        }

        /// <summary>
        /// 设置是否在节点旁显示复选框
        /// </summary>
        public virtual void setCheckBoxes(bool value)
        {
            m_checkBoxes = value;
        }

        public FCSize m_checkBoxSize = new FCSize(14, 14);

        /// <summary>
        /// 获取复选框的大小
        /// </summary>
        public virtual FCSize getCheckBoxSize()
        {
            return m_checkBoxSize;
        }

        /// <summary>
        /// 设置复选框的大小
        /// </summary>
        public virtual void setCheckBoxSize(FCSize value)
        {
            m_checkBoxSize = value;
        }

        public String m_checkedImage;

        /// <summary>
        /// 获取复选框选中时的图片
        /// </summary>
        public virtual String getCheckedImage()
        {
            return m_checkedImage;
        }

        /// <summary>
        /// 设置复选框选中时的图片
        /// </summary>
        public virtual void setCheckedImage(String value)
        {
            m_checkedImage = value;
        }

        public String m_collapsedNodeImage;

        /// <summary>
        /// 获取折叠节点的图片
        /// </summary>
        public virtual String getCollapsedNodeImage()
        {
            return m_collapsedNodeImage;
        }

        /// <summary>
        /// 设置折叠节点的图片
        /// </summary>
        public virtual void setCollapsedNodeImage(String value)
        {
            m_collapsedNodeImage = value;
        }

        public String m_expendedNodeImage;

        /// <summary>
        /// 获取展开节点的图片
        /// </summary>
        public virtual String getExpendedNodeImage()
        {
            return m_expendedNodeImage;
        }

        /// <summary>
        /// 设置展开节点的图片
        /// </summary>
        public virtual void setExpendedNodeImage(String value)
        {
            m_expendedNodeImage = value;
        }

        public FCSize m_nodeSize = new FCSize(14, 14);

        /// <summary>
        /// 获取节点的大小
        /// </summary>
        public virtual FCSize getNodeSize()
        {
            return m_nodeSize;
        }

        /// <summary>
        /// 设置节点的大小
        /// </summary>
        public virtual void setNodeSize(FCSize value)
        {
            m_nodeSize = value;
        }

        /// <summary>
        /// 获取或设置选中的节点
        /// </summary>
        public virtual ArrayList<FCTreeNode> getSelectedNodes()
        {
            ArrayList<FCTreeNode> selectedNodes = new ArrayList<FCTreeNode>();
            ArrayList<FCGridRow> selectedRows = getSelectedRows();
            int selectedRowsSize = selectedRows.size();
            for (int i = 0; i < selectedRowsSize; i++)
            {
                ArrayList<FCGridCell> cells = selectedRows.get(i).m_cells;
                int cellsSize = cells.size();
                for (int j = 0; j < cellsSize; j++)
                {
                    FCTreeNode node = cells.get(j) as FCTreeNode;
                    if (node != null)
                    {
                        selectedNodes.add(node);
                        break;
                    }
                }
            }
            return selectedNodes;
        }

        /// <summary>
        /// 设置选中的节点
        /// </summary>
        public virtual void setSelectedNodes(ArrayList<FCTreeNode> value)
        {
            int selectedNodesSize = value.size();
            ArrayList<FCGridRow> selectedRows = new ArrayList<FCGridRow>();
            for (int i = 0; i < selectedNodesSize; i++)
            {
                selectedRows.add(value.get(i).getRow());
            }
            setSelectedRows(selectedRows);
        }

        public String m_unCheckedImage;

        /// <summary>
        /// 获取复选框未选中时的图片
        /// </summary>
        public virtual String getUnCheckedImage()
        {
            return m_unCheckedImage;
        }

        /// <summary>
        /// 设置复选框未选中时的图片
        /// </summary>
        public virtual void setUnCheckedImage(String value)
        {
            m_unCheckedImage = value;
        }

        /// <summary>
        /// 添加节点
        /// </summary>
        /// <param name="node">节点</param>
        public virtual void appendNode(FCTreeNode node)
        {
            node.setTree(this);
            node.onAddingNode(-1);
            m_nodes.add(node);
        }

        /// <summary>
        /// 清除所有节点
        /// </summary>
        public virtual void clearNodes()
        {
            while (m_nodes.size() > 0)
            {
                removeNode(m_nodes.get(m_nodes.size() - 1));
            }
        }

        /// <summary>
        /// 折叠节点
        /// </summary>
        public virtual void collapse()
        {
            int nodesSize = m_nodes.size();
            if (nodesSize > 0)
            {
                for (int i = 0; i < nodesSize; i++)
                {
                    m_nodes.get(i).collapse();
                }
            }
        }

        /// <summary>
        /// 折叠节点
        /// </summary>
        public virtual void collapseAll()
        {
            int nodesSize = m_nodes.size();
            if (nodesSize > 0)
            {
                for (int i = 0; i < nodesSize; i++)
                {
                    m_nodes.get(i).collapseAll();
                }
            }
        }

        /// <summary>
        /// 销毁资源
        /// </summary>
        public override void delete()
        {
            if (!isDeleted())
            {
                m_nodes.clear();
            }
            base.delete();
        }

        /// <summary>
        /// 展开节点
        /// </summary>
        public virtual void expend()
        {
            int nodesSize = m_nodes.size();
            if (nodesSize > 0)
            {
                for (int i = 0; i < nodesSize; i++)
                {
                    m_nodes.get(i).expend();
                }
            }
        }

        /// <summary>
        /// 展开节点
        /// </summary>
        public virtual void expendAll()
        {
            int nodesSize = m_nodes.size();
            if (nodesSize > 0)
            {
                for (int i = 0; i < nodesSize; i++)
                {
                    m_nodes.get(i).expendAll();
                }
            }
        }

        /// <summary>
        /// 获取子节点
        /// </summary>
        /// <returns>子节点</returns>
        public virtual ArrayList<FCTreeNode> getChildNodes()
        {
            return m_nodes;
        }

        /// <summary>
        /// 获取视图类型
        /// </summary>
        /// <returns>视图类型</returns>
        public override String getViewType()
        {
            return "Tree";
        }

        /// <summary>
        /// 获取节点的索引
        /// </summary>
        /// <param name="node">节点</param>
        /// <returns>索引</returns>
        public virtual int getNodeIndex(FCTreeNode node)
        {
            int nodeSize = m_nodes.size();
            for (int i = 0; i < nodeSize; i++)
            {
                if (m_nodes.get(i) == node)
                {
                    return i;
                }
            }
            return -1;
        }

        /// <summary>
        /// 获取属性值
        /// </summary>
        /// <param name="name">属性名称</param>
        /// <param name="value">返回属性值</param>
        /// <param name="type">返回属性类型</param>
        public override void getAttribute(String name, ref String value, ref String type)
        {
            switch (name)
            {
                case "checkboxes":
                    type = "bool";
                    value = FCTran.boolToStr(hasCheckBoxes());
                    break;
                case "checkboxsize":
                    type = "size";
                    value = FCTran.sizeToStr(getCheckBoxSize());
                    break;
                case "checkedimage":
                    type = "text";
                    value = getCheckedImage();
                    break;
                case "collapsednodeimage":
                    type = "text";
                    value = getCollapsedNodeImage();
                    break;
                case "expendednodeimage":
                    type = "text";
                    value = getExpendedNodeImage();
                    break;
                case "uncheckedimage":
                    type = "text";
                    value = getUnCheckedImage();
                    break;
                case "nodesize":
                    type = "size";
                    value = FCTran.sizeToStr(getNodeSize());
                    break;
                default:
                    base.getAttribute(name, ref value, ref type);
                    break;
            }
        }

        /// <summary>
        /// 获取属性名称列表
        /// </summary>
        /// <returns>属性名称列表</returns>
        public override ArrayList<String> getAttributeNames()
        {
            ArrayList<String> attributeNames = base.getAttributeNames();
            attributeNames.AddRange(new String[] { "CheckBoxes", "CheckBoxSize", "CheckedImage", "CollapsedNodeImage", "ExpendedNodeImage", "UnCheckedImage", "NodeSize" });
            return attributeNames;
        }

        /// <summary>
        /// 插入节点
        /// </summary>
        /// <param name="index">索引</param>
        /// <param name="node">节点</param>
        public void insertNode(int index, FCTreeNode node)
        {
            int rowIndex = -1;
            if (index == 0)
            {
                if (node.getParent() != null)
                {
                    rowIndex = node.getParent().getRow().getIndex() + 1;
                }
                else
                {
                    rowIndex = 0;
                }
            }
            else
            {
                if (m_nodes.size() > 0)
                {
                    rowIndex = m_nodes.get(index).getRow().getIndex();
                }
            }
            node.setTree(this);
            node.onAddingNode(rowIndex);
            m_nodes.Insert(index, node);
        }

        /// <summary>
        /// 单元格触摸按下方法
        /// </summary>
        /// <param name="cell">单元格</param>
        /// <param name="touchInfo">触摸信息</param>
        public override void onCellTouchDown(FCGridCell cell, FCTouchInfo touchInfo)
        {
            FCTreeNode oldSelectedNode = null;
            ArrayList<FCTreeNode> selectedNodes = getSelectedNodes();
            if (selectedNodes.size() > 0)
            {
                oldSelectedNode = selectedNodes.get(0);
            }
            FCHost host = getNative().getHost();
            base.onCellTouchDown(cell, touchInfo);
            if (touchInfo.m_firstTouch)
            {
                FCPoint mp = touchInfo.m_firstPoint;
                FCTreeNode node = cell as FCTreeNode;
                if (node != null)
                {
                    int scrollH = 0;
                    FCHScrollBar hscrollBar = getHScrollBar();
                    if (hscrollBar != null && hscrollBar.isVisible())
                    {
                        scrollH = hscrollBar.getPos();
                    }
                    FCRect headerRect = node.getTargetColumn().getBounds();
                    headerRect.left += getHorizontalOffset() - scrollH;
                    headerRect.top += getVerticalOffset() - scrollH;
                    int left = headerRect.left;
                    //复选框
                    if (m_checkBoxes)
                    {
                        int cw = m_checkBoxSize.cx;
                        if (mp.x >= left && mp.x <= left + cw)
                        {
                            if (host.isKeyPress(0x10) && oldSelectedNode != null && oldSelectedNode != node)
                            {
                                int sIndex = oldSelectedNode.getRow().getIndex();
                                int eIndex = node.getRow().getIndex();
                                int minIndex = Math.Min(sIndex, eIndex);
                                int maxIndex = Math.Max(eIndex, eIndex);
                                for (int i = minIndex; i <= maxIndex; i++)
                                {
                                    FCTreeNode iNode = (FCTreeNode)m_rows.get(i).getCell(0);
                                    iNode.setChecked(oldSelectedNode.isChecked());
                                }
                            }
                            else
                            {
                                node.setChecked(!node.isChecked());
                            }
                            return;
                        }
                        left += cw + 10;
                    }
                    //折叠节点
                    ArrayList<FCTreeNode> childNodes = node.getChildNodes();
                    if (childNodes != null && childNodes.size() > 0)
                    {
                        int nw = m_nodeSize.cx;
                        if (mp.x >= left && mp.x <= left + nw)
                        {
                            if (node.isExpended())
                            {
                                node.collapse();
                            }
                            else
                            {
                                node.expend();
                            }
                            update();
                            return;
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 单元格触摸移动方法
        /// </summary>
        /// <param name="cell">单元格</param>
        /// <param name="touchInfo">触摸信息</param>
        public override void onCellTouchMove(FCGridCell cell, FCTouchInfo touchInfo)
        {
            base.onCellTouchMove(cell, touchInfo);
            if (touchInfo.m_firstTouch)
            {
                if (m_movingNode == null)
                {
                    FCPoint mp = touchInfo.m_firstPoint;
                    FCTreeNode node = cell as FCTreeNode;
                    if (node != null && node.allowDragOut())
                    {
                        if (Math.Abs(m_touchDownPoint.y - mp.y) > 5)
                        {
                            m_movingNode = node;
                        }
                    }
                }
                if (m_movingNode != null)
                {
                    invalidate();
                }
            }
        }

        /// <summary>
        /// 单元格触摸抬起方法
        /// </summary>
        /// <param name="cell">单元格</param>
        /// <param name="touchInfo">触摸信息</param>
        public override void onCellTouchUp(FCGridCell cell, FCTouchInfo touchInfo)
        {
            base.onCellTouchUp(cell, touchInfo);
            FCPoint mp = touchInfo.m_firstPoint;
            if (m_movingNode != null)
            {
                FCGridRow curRow = getRow(mp);
                //移动
                if (curRow != null)
                {
                    FCTreeNode curNode = curRow.getCell(0) as FCTreeNode;
                    if (curNode.allowDragIn() && m_movingNode != curNode)
                    {
                        bool isParent = false;
                        FCTreeNode parentNode = curNode.getParent();
                        if (parentNode == m_movingNode)
                        {
                            isParent = true;
                        }
                        else
                        {
                            while (parentNode != null)
                            {
                                parentNode = parentNode.getParent();
                                if (parentNode == m_movingNode)
                                {
                                    isParent = true;
                                    break;
                                }
                            }
                        }
                        if (!isParent)
                        {
                            FCTreeNode curNodeParent = curNode.getParent();
                            FCTreeNode movingNodeParent = m_movingNode.getParent();
                            if (movingNodeParent != null)
                            {
                                movingNodeParent.removeNode(m_movingNode);
                            }
                            else
                            {
                                removeNode(m_movingNode);
                            }
                            curNode.appendNode(m_movingNode);
                            curNode.expend();
                        }
                    }
                }
                m_movingNode = null;
                update();
            }
        }

        /// <summary>
        /// 重绘前景方法
        /// </summary>
        /// <param name="paint">绘图对象</param>
        /// <param name="clipRect">裁剪区域</param>
        public override void onPaintForeground(FCPaint paint, FCRect clipRect)
        {
            base.onPaintForeground(paint, clipRect);
            //绘制移动的节点
            if (m_movingNode != null)
            {
                FCFont font = getFont();
                FCPoint mp = getTouchPoint();
                FCSize tSize = paint.textSize(m_movingNode.getText(), font, -1);
                FCRect tRect = new FCRect(mp.x, mp.y, mp.x + tSize.cx, mp.y + tSize.cy);
                paint.fillRect(getBackColor(), tRect);
                paint.drawRect(getTextColor(), 1, 0, tRect);
                paint.drawText(m_movingNode.getText(), getTextColor(), font, tRect, -1);
            }
        }

        /// <summary>
        /// 绘制编辑文本框
        /// </summary>
        /// <param name="cell">单元格</param>
        /// <param name="paint">绘图对象</param>
        /// <param name="rect">区域</param>
        /// <param name="clipRect">裁剪区域</param>
        public override void onPaintEditTextBox(FCGridCell cell, FCPaint paint, FCRect rect, FCRect clipRect)
        {
            FCTextBox editTextBox = getEditTextBox();
            if (editTextBox != null)
            {
                FCTreeNode node = cell as FCTreeNode;
                if (node != null)
                {
                    int indent = node.getIndent();
                    rect.left += indent;
                    if (rect.right < rect.left)
                    {
                        rect.right = rect.left;
                    }
                    editTextBox.setBounds(rect);
                    editTextBox.setDisplayOffset(false);
                    editTextBox.bringToFront();
                }
                else
                {
                    base.onPaintEditTextBox(cell, paint, rect, clipRect);
                }
            }
        }

        /// <summary>
        /// 移除节点
        /// </summary>
        /// <param name="node">节点</param>
        public void removeNode(FCTreeNode node)
        {
            node.onRemovingNode();
            m_nodes.remove(node);
        }

        /// <summary>
        /// 设置属性
        /// </summary>
        /// <param name="name">属性名</param>
        /// <param name="value">属性值</param>
        public override void setAttribute(String name, String value)
        {
            switch (name)
            {
                case "checkboxes":
                    setCheckBoxes(FCTran.strToBool(value));
                    break;
                case "checkboxsize":
                    setCheckBoxSize(FCTran.strToSize(value));
                    break;
                case "checkedimage":
                    setCheckedImage(value);
                    break;
                case "collapsednodeimage":
                    setCollapsedNodeImage(value);
                    break;
                case "expendednodeimage":
                    setExpendedNodeImage(value);
                    break;
                case "uncheckedimage":
                    setUnCheckedImage(value);
                    break;
                case "nodesize":
                    setNodeSize(FCTran.strToSize(value));
                    break;
                default:
                    base.setAttribute(name, value);
                    break;
            }
        }
    }
}
